
from django.core.validators import RegexValidator
from django import forms
from web import models
from django.core.exceptions import ValidationError
from django.conf import settings
from utils.tencent.sms import send_sms_single
import random

from django_redis import get_redis_connection
from utils import encrypt
from web.forms.bootstrap import BootStrapForm


# Create your views here.

# class MobilePhoneModelForm(forms.ModelForm):
class MobilePhoneModelForm(forms.Form):
    mobile_phone = forms.CharField(
        validators=[RegexValidator(r'^1[3|4|5|6|7|8]\d{9}$','手机号码格式错误'),],
        label='手机号码',
        widget=forms.TextInput()
    )     
    # class Meta:
    #     model=models.UserInfo
    #     fields=['mobile_phone']

class MobilePhoneSMSModelForm(MobilePhoneModelForm):
    
    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request  #为了多传一个数据
    
    def clean_mobile_phone(self):

        mobile_phone = self.cleaned_data.get('mobile_phone')
        existed = models.UserInfo.objects.filter(mobile_phone=self.cleaned_data['mobile_phone']).first()
        
        if self.request.GET.get('tpl') =="register":
            if existed:
                # raise ValidationError("手机号已存在")
                self.add_error('mobile_phone','手机号已存在')
                return mobile_phone
        else:
            if not existed:
                self.add_error('mobile_phone','手机号不存在')
                return mobile_phone

        if self.request.GET.get('tpl') not in settings.TENCENT_SMS_TEMPLATE.keys():
            # raise ValidationError("短信验证模式错误")
            self.add_error('mobile_phone','短信验证模式错误')
            return mobile_phone
        
        # 发短信验证&写验证码
        # 为了让出错信息都保存在’手机号码‘下面
        code = random.randrange(1000,9999)
        template_id = settings.TENCENT_SMS_TEMPLATE.get('tpl')
        if not settings.TENCENT_SMS_DISABLE:    # fail to apply for 腾讯云
            sms = send_sms_single(mobile_phone, template_id,[code,])
            if sms['result']!=0:
                # 短信发送失败，报错
                # raise ValidationError("短信发送失败，{}".format(sms['errmsg']))
                self.add_error('mobile_phone',"短信发送失败，{}".format(sms['errmsg'])) 
        # 短信发送成功，写入redis
        conn = get_redis_connection('default')
        conn.set(mobile_phone, code, ex=600)
                   
        return mobile_phone
    
class LoginSMSModelForm(BootStrapForm, forms.Form):
    mobile_phone = forms.CharField(
        validators=[RegexValidator(r'^1[3|4|5|6|7|8]\d{9}$','手机号码格式错误'),],
        label='手机号码',
        widget=forms.TextInput()
    )     
    
    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())
    
    # class Meta:
    #     model=models.UserInfo
    #     fields=['mobile_phone','code']
       
    def clean_code(self):
        code = self.cleaned_data['code']
        conn = get_redis_connection('default')
        if 'mobile_phone' in self.cleaned_data.keys():
            value = conn.get(self.cleaned_data['mobile_phone']) 
            if not value:
                # raise ValidationError("请先获取短信验证码")
                self.add_error('code',"请先获取短信验证码")
            else:
                value = value.decode('utf-8')   #bytes转字符串
            if code.strip() != value:
                # raise ValidationError("输入验证码不匹配")
                self.add_error('code',"输入验证码不匹配")
        return code
    
    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        existed = models.UserInfo.objects.filter(mobile_phone= mobile_phone).first()
        if not existed:
            # raise ValidationError("手机号码不存在")
            self.add_error('mobile_phone',"手机号码不存在")
        return mobile_phone

class LoginModelForm(BootStrapForm,forms.Form):
    emailorphone = forms.CharField(
        label='邮箱或手机号',
        widget=forms.TextInput())

    password = forms.CharField(
        min_length=4,
        label='密码',
        widget=forms.PasswordInput(render_value=True))

    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())
   
   
    # class Meta:
    #     # model=models.UserInfo
    #     fields=['emailorphone','password','code']
        
    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request
        
    def clean_username(self):
        username = self.cleaned_data['username']
        user_existed = models.UserInfo.objects.filter(username=username).exists()

        if not user_existed:
            # raise ValidationError("用户名已存在")
            self.add_error('username',"用户名不存在")
        # return self.cleaned_data['username']
        return username
    def clean_emailorphone(self):
        emailorphone = self.cleaned_data['emailorphone']
        from django.db.models import Q
        user_existed = models.UserInfo.objects.filter(Q(email=emailorphone) | Q(mobile_phone=emailorphone)).exists()

        if not user_existed:
            # raise ValidationError("用户名已存在")
            self.add_error('emailorphone',"邮箱或手机号不存在")
        # return self.cleaned_data['username']
        return emailorphone

    def clean_password(self):
        password = self.cleaned_data['password']
        encrypt_pwd = encrypt.md5(password)
        if 'emailorphone' in self.cleaned_data.keys():
            emailorphone = self.cleaned_data['emailorphone']
            from django.db.models import Q
            user_existed = models.UserInfo.objects.filter(Q(email=emailorphone) |  
                            Q(mobile_phone=emailorphone)).filter(password=encrypt_pwd).exists()
            # existed = models.UserInfo.objects.filter(username=username, password=encrypt_pwd).exists()
            if not user_existed:
                self.add_error('password','密码不匹配,请重新输入')
        # md5 encrypt, saved in database 
        return password 
    
    def clean_code(self):
        code = self.cleaned_data['code']
        value = self.request.session.get('image_code')
        if not value:
            self.add_error('code','验证码已过期,请刷新')
        else:
            if code.upper().strip()!=value:
                self.add_error('code','验证码输入不正确')
        
        return code



class RegisterModelForm(BootStrapForm, forms.ModelForm):

    password = forms.CharField(
        min_length=4,
        label='密码',
        widget=forms.PasswordInput(render_value=True))

    confirm_password = forms.CharField(
        min_length=4,
        label='重复密码',
        widget=forms.PasswordInput())
    
    mobile_phone = forms.CharField(
        validators=[RegexValidator(r'^1[3|4|5|6|7|8]\d{9}$','手机号码格式错误'),],
        label='手机号码',
        widget=forms.TextInput())
      
    code = forms.CharField(
        label='验证码',
        widget=forms.TextInput())
    
    class Meta:
        model=models.UserInfo
        fields=['username', 'email', 'password', 'confirm_password', 'mobile_phone']
    
    
    def __init__(self, request, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.request = request
    
    def clean(self):
        return self.cleaned_data

    def clean_username(self):
        username = self.cleaned_data['username']
        user_existed = models.UserInfo.objects.filter(username=username).first()

        if user_existed:
            # raise ValidationError("用户名已存在")
            self.add_error('username',"用户名已存在")
        # return self.cleaned_data['username']
        return username

    def clean_code(self):
        code = self.cleaned_data['code']
        conn = get_redis_connection('default')
        if 'mobile_phone' in self.cleaned_data.keys():
            value = conn.get(self.cleaned_data['mobile_phone']) 
            if not value:
                # raise ValidationError("请先获取短信验证码")
                self.add_error('code',"请先获取短信验证码")
            else:
                value = value.decode('utf-8')
            
            if code.strip() != value:
                # raise ValidationError("输入验证码不匹配")
                self.add_error('code',"输入验证码不匹配")

        return code
    
    def clean_mobile_phone(self):
        mobile_phone = self.cleaned_data['mobile_phone']
        existed = models.UserInfo.objects.filter(mobile_phone= mobile_phone).exists()
        if existed:
            # raise ValidationError("手机号码已经存在")
            self.add_error('mobile_phone',"手机号码已经存在")
        return mobile_phone

    def clean_email(self):
        email = self.cleaned_data['email']
        existed = models.UserInfo.objects.filter(email = email).exists()
        if existed:
            # raise ValidationError("邮箱已经存在")
            self.add_error('email',"邮箱已经存在")
        return email
    
    def clean_password(self):
        password = self.cleaned_data['password']
        # md5 encrypt, saved in database 
        return encrypt.md5(password)
    
    def clean_confirm_password(self):
        confirm_password = self.cleaned_data['confirm_password']
        if 'password' in self.cleaned_data.keys():
            if encrypt.md5(confirm_password)!=self.cleaned_data['password']:
                    # raise ValidationError('二次输入密码不一致') 
                    self.add_error('confirm_password',"二次输入密码不一致")
        return confirm_password
        
